<template>
	<view class="voice-visualizer">
		<view class="wave-container" :class="{ 'loading': isLoading }">
			<!-- 识别中：加载动画 -->
			<view class="loading-dots" v-if="isLoading">
				<view class="dot"></view>
				<view class="dot"></view>
				<view class="dot"></view>
			</view>
			<!-- 录音中：柱条 -->
			<view class="wave-bar" v-for="(height, index) in waveBars" :key="index"
				:style="{ height: height + 'rpx', backgroundColor: barColors[index] }" v-if="!isLoading"></view>
		</view>
		</view>
	</template>

	<script lang="ts" setup>
	import { ref, computed, watch, onMounted, onUnmounted } from 'vue';

	const props = defineProps({
		volume: {
			type: Number,
			default: 0,
			validator: (val: number) => val >= 0 && val <= 1
		},
		isLoading: {
			type: Boolean,
			default: false
		},
		barCount: {
			type: Number,
			default: 18,
			validator: (val: number) => val >= 5 && val <= 30
		},
		maxHeight: {
			type: Number,
			default: 220,
			validator: (val: number) => val >= 100 && val <= 300
		}
	});

	const waveBars = ref<number[]>([]);
	const barColors = ref<string[]>([]);
	let animationTimer: NodeJS.Timeout | null = null;

	// 基础高度（音量为0时的最小高度）
	const baseHeight = computed(() => props.maxHeight * 0.5);
	// 🔴 硬性限制最大可用高度（留10%余量，绝对不顶满）
	const safeMaxHeight = computed(() => props.maxHeight * 0.9);
	// 可用高度范围（基础到安全最大）
	const heightRange = computed(() => safeMaxHeight.value - baseHeight.value);

	// 颜色渐变配置
	const colorGradients = computed(() => ['#00C896', '#007AFF', '#FF9500', '#FF3B30']);

	// 初始化柱条
	const initBars = () => {
		waveBars.value = Array(props.barCount).fill(baseHeight.value);
		barColors.value = Array(props.barCount).fill('').map((_, index) => {
			const ratio = index / props.barCount;
			return ratio < 0.3 ? colorGradients.value[0]
				: ratio < 0.6 ? colorGradients.value[1]
					: ratio < 0.8 ? colorGradients.value[2]
						: colorGradients.value[3];
		});
	};

	// 🔴 核心修复：非线性映射+硬性高度限制
	const calculateBarHeights = () => {
		if (props.isLoading) return;

		waveBars.value = waveBars.value.map(oldHeight => {
			// 1. 非线性映射：音量越高，增长越平缓（用平方根曲线）
			const volumePower = Math.sqrt(props.volume); // 替代直接使用props.volume
			
			// 2. 限制音量影响力（最大发挥60%的可用高度）
			const volumeInfluence = volumePower * 0.6;
			
			// 3. 缩小随机因子范围（0.4-0.8），避免极端值
			const randomFactor = 0.4 + Math.random() * 0.4;
			
			// 4. 计算目标高度
			const targetHeight = baseHeight.value + (heightRange.value * volumeInfluence * randomFactor);
			
			// 5. 双重保险：确保不超过安全最大高度
			const finalHeight = Math.min(targetHeight, safeMaxHeight.value);
			
			// 6. 平滑过渡（降低惯性，避免累积过高）
			return (oldHeight * 0.3) + (finalHeight * 0.7); // 新高度权重更高
		});
	};

	// 动画控制（降低频率，减少抖动）
	const startAnimation = () => {
		stopAnimation();
		animationTimer = setInterval(calculateBarHeights, 50);
	};

	const stopAnimation = () => {
		if (animationTimer) {
			clearInterval(animationTimer);
			animationTimer = null;
		}
	};

	// 监听识别状态
	watch(() => props.isLoading, (isNowLoading) => {
		if (isNowLoading) {
			stopAnimation();
		} else {
			waveBars.value = Array(props.barCount).fill(baseHeight.value);
			startAnimation();
		}
	});

	// 监听音量变化
	watch(() => props.volume, (newVolume) => {
		if (!props.isLoading) {
			calculateBarHeights();
		}
	}, { immediate: true });

	onMounted(() => {
		initBars();
		if (!props.isLoading) startAnimation();
	});

	onUnmounted(stopAnimation);
	</script>

	<style scoped lang="scss">
	$prefix: voice-visualizer;

	.#{$prefix} {
		display: flex;
		justify-content: center;
		align-items: flex-end;
		height: 260rpx;
		width: 100%;
	}

	.wave-container {
		display: flex;
		align-items: flex-end;
		gap: 8rpx;
		height: 100%;
		width: 100%;
		max-width: 500rpx;
		justify-content: space-evenly;

		&.loading {
			justify-content: center;
			align-items: center;
		}
	}

	.wave-bar {
		width: 14rpx;
		border-radius: 7rpx;
		background-color: #007AFF;
		transition: height 0.05s ease-out; // 加入过渡动画，视觉更平滑
	}

	.loading-dots {
		display: flex;
		gap: 15rpx;

		.dot {
			width: 18rpx;
			height: 18rpx;
			border-radius: 50%;
			background-color: #007AFF;
			animation: bounce 1.4s infinite ease-in-out both;

			&:nth-child(1) { animation-delay: -0.32s; }
			&:nth-child(2) { animation-delay: -0.16s; }
		}
	}

	@keyframes bounce {
		0%, 80%, 100% { transform: scale(0); }
		40% { transform: scale(1); }
	}
	</style>
